package sgd.tp2.server.net;

import java.io.IOException;

import com.espertech.esper.client.Configuration;
import com.espertech.esper.client.EPServiceProvider;
import com.espertech.esper.client.EPServiceProviderManager;

import sgd.tp2.api.cdr.CDR;
import sgd.tp2.api.logging.Log;
import sgd.tp2.api.net.CDRFormatType;
import sgd.tp2.api.net.CEPType;
import sgd.tp2.server.esper.EPStatistics;
import sgd.tp2.server.metrics.MessageMetric;
import sgd.tp2.server.metrics.Metrics;

public abstract class Server implements Runnable {

	protected Metrics metrics = null;
	protected MessageMetric currentMessageMetric = null;
	protected int port = -1;
	protected CDRFormatType cdrFormatType = null;

	protected CEPType cepType = CEPType.NONE;
	protected EPServiceProvider epService = null;
	protected EPStatistics epStatistics = null;

	public Server() {
		this(CDRFormatType.XML, 1234, CEPType.NONE);
	}

	public Server(CDRFormatType cdrFormatType, int port, CEPType cepType) {
		this.cdrFormatType = cdrFormatType;
		this.port = port;
		this.metrics = new Metrics(cdrFormatType);
		this.cepType = cepType;

		// Build Esper service if needed
		if (cepType == CEPType.ESPER) {
			epStatistics = new EPStatistics();

			Configuration cfg = new Configuration();
			cfg.addEventTypeAutoName(CDR.class.getPackage().getName());

			epService = EPServiceProviderManager.getDefaultProvider(cfg);

			// Calls Per Second
			//epService.getEPAdministrator().createEPL(epStatistics.getExpression())
			//		.addListener(epStatistics);
		}
	}

	public abstract void startServer() throws IOException;

	public abstract void stopServer();

	public void receivedCDR() {
		Log.insertString("|");
		metrics.messageArrived(currentMessageMetric = new MessageMetric());
	}

	public void startCDRHandling() {
		metrics.messageStartHandling(currentMessageMetric);
	}

	public void handleCDR(CDR cdr) {
		metrics.callReceived(cdr.getCallerId(), cdr.getmDuration());

		if (cepType == CEPType.ESPER)
			epService.getEPRuntime().sendEvent(cdr);
	}

	public void endCDRHandling(CDR cdr) {
		metrics.messageEndHandling(currentMessageMetric, cdr);
	}

	public void printMetrics() {
		metrics.setLastMessageReceivedTime(System.nanoTime());
		metrics.print();
	}
}
